﻿using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _02创建图形
{
    public static partial class AddEntityTool
    {
        /// <summary>
        /// 将图形对象添加到图形文件中
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="ent">图形对象</param>
        /// <returns>图形的ObjectId</returns>
        public static ObjectId AddEnityToModelSpace(this Database db,Entity ent)
        {
            //声明ObjectId,用于返回
            ObjectId entId = ObjectId.Null;
            //开启事务处理
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                //打开块表
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                //打开块表记录
                BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                //添加图形到块表记录
                entId = btr.AppendEntity(ent);
                //更新数据信息
                trans.AddNewlyCreatedDBObject(ent, true);
                //提交事务
                trans.Commit();
            }
            return entId;
        }
        /// <summary>
        /// 将图形对象添加到图形文件中
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="ent">图形对象,可变参数</param>
        /// <returns>图形的ObjectId,数组返回</returns>
        public static ObjectId[] AddEnityToModelSpace(this Database db, params Entity[] ent)
        {
            //声明ObjectId,用于返回
            ObjectId[] entId = new ObjectId[ent.Length];
            //开启事务处理
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                //打开块表
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                //打开块表记录
                BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
               
                for (int i = 0; i < ent.Length; i++)
                {
                    //添加图形到块表记录
                    entId[i] = btr.AppendEntity(ent[i]);
                    //更新数据信息
                    trans.AddNewlyCreatedDBObject(ent[i], true);
                }
                
                //提交事务
                trans.Commit();
            }
            return entId;
        }
        /// <summary>
        /// 绘制直线
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="startPoint">起点坐标</param>
        /// <param name="endPoint">终点坐标</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddLineToModelSpace(this Database db, Point3d startPoint, Point3d endPoint)
        {
            return db.AddEnityToModelSpace(new Line(startPoint, endPoint));
        }
        /// <summary>
        /// 绘制直线
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="startPoint">起点坐标</param>
        /// <param name="length">直线长度</param>
        /// <param name="degree">与X轴正方向的角度</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddLineToModelSpace(this Database db, Point3d startPoint, Double length, Double degree)
        {
            //计算终点坐标
            double X = startPoint.X + length * Math.Cos(degree.DegreeToAngle());
            double Y = startPoint.Y + length * Math.Sin(degree.DegreeToAngle());
            Point3d endPoint = new Point3d(X,Y,0);
            return db.AddEnityToModelSpace(new Line(startPoint, endPoint));
        }
        /// <summary>
        /// 绘制圆弧
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="center">圆弧所在圆的圆心点</param>
        /// <param name="radius">圆弧的半径</param>
        /// <param name="startDegree">圆弧的起始角度</param>
        /// <param name="endDegree">圆弧的终止角度</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddArcToModelSpace(this Database db, Point3d center, double radius, double startDegree, double endDegree)
        {
            return db.AddEnityToModelSpace(new Arc(center, radius, startDegree.DegreeToAngle(), endDegree.DegreeToAngle()));
        }
        /// <summary>
        /// 通过三点创建圆弧
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="startPoint">起点</param>
        /// <param name="pointOnArc">圆弧上的点</param>
        /// <param name="endPoint">终点</param>
        /// <returns></returns>
        public static ObjectId AddArcToModelSpace(this Database db, Point3d startPoint, Point3d pointOnArc, Point3d endPoint)
        {
            //先判断三点是否在同一条直线上
            if (startPoint.IsOnOneLine(pointOnArc,endPoint))
            {
                return ObjectId.Null;
            }
            
            //创建几何类对象
            CircularArc3d cArc = new CircularArc3d(startPoint, pointOnArc, endPoint);
            //通过几何类对象获取其属性
            //double radius = cArc.Radius; //半径
            //Point3d center = cArc.Center; //所在圆的圆心
            //Vector3d cs = center.GetVectorTo(startPoint); //圆心到起点的向量
            //Vector3d ce = center.GetVectorTo(endPoint);   //圆心到终点的向量
            //Vector3d xVector = new Vector3d(1, 0, 0); //X正方向的向量
            ////圆弧的起始角度
            //double startAngle = cs.Y > 0 ? xVector.GetAngleTo(cs) : -xVector.GetAngleTo(cs);
            ////圆弧的终止角度
            //double endAngle = ce.Y > 0 ? xVector.GetAngleTo(ce) : -xVector.GetAngleTo(ce);

            //创建圆弧对象
            Arc arc = new Arc(cArc.Center, cArc.Radius, cArc.Center.GetAngleToXAxis(startPoint), cArc.Center.GetAngleToXAxis(endPoint));
            //加入图形数据库
            return db.AddEnityToModelSpace(arc);
        }
        /// <summary>
        /// 通过圆心、起点，夹角绘制圆弧
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="center">圆心</param>
        /// <param name="startPoint">起点</param>
        /// <param name="degree">夹角,角度值</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddArcToModelSpace(this Database db, Point3d center, Point3d startPoint, double degree)
        {
            //获取半径
            double radius = center.GetDistanceBetweenTwoPoint(startPoint);
            //获取起点角度
            double startAngle = center.GetAngleToXAxis(startPoint);
            //声明圆弧对象
            Arc arc = new Arc(center, radius, startAngle, startAngle + degree.DegreeToAngle());
            return db.AddEnityToModelSpace(arc);

        }

        /// <summary>
        /// 绘制圆
        /// </summary>
        /// <param name="db">图形据据库</param>
        /// <param name="center">圆心</param>
        /// <param name="radius">半径</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddCircleModelSpace(this Database db, Point3d center, double radius)
        {
            return db.AddEnityToModelSpace(new Circle(center, new Vector3d(0, 0, 1), radius));
        }
        /// <summary>
        /// 两点绘制圆
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="point1">第一个点</param>
        /// <param name="point2">第二个点</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddCircleModelSpace(this Database db, Point3d point1, Point3d point2)
        {
            //获取中心点
            Point3d center = point1.GetCenterPointBetweenTwoPoint(point2);
            //获取半径
            double radius = point1.GetDistanceBetweenTwoPoint(center);
            return db.AddCircleModelSpace(center, radius);
        }
        /// <summary>
        /// 三点绘制圆
        /// </summary>
        ///<param name="db">图形数据库</param>
        /// <param name="point1">第一个点</param>
        /// <param name="point2">第二个点</param>
        /// <param name="point3">第三个点</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddCircleModelSpace(this Database db, Point3d point1, Point3d point2, Point3d point3)
        {
            //先判断三点是否在同一条直线上
            if (point1.IsOnOneLine(point2, point3))
            {
                return ObjectId.Null;
            }
            //声明几何类的CircularArc3d对象
            CircularArc3d cArc = new CircularArc3d(point1, point2, point3);
            return db.AddCircleModelSpace(cArc.Center, cArc.Radius);
        }
        /// <summary>
        /// 绘制折线多段线
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="isClosed">是否闭合</param>
        /// <param name="constantWidth">线宽</param>
        /// <param name="vertices">多段线的定点,可变参数</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddPolyLineToModelSpace(this Database db, bool isClosed, double constantWidth, params Point2d[] vertices)
        {
            if (vertices.Length < 2 )
            {
                return ObjectId.Null;
            }
            //声明一个多段线对象
            Polyline pLine = new Polyline();
            //添加多段线的顶点
            for (int i = 0; i < vertices.Length; i++)
            {
                pLine.AddVertexAt(i, vertices[i], 0, 0, 0);
            }
            //判断是否闭合
            if (isClosed)
            {
                pLine.Closed = true;
            }
            //设置多段线的线宽
            pLine.ConstantWidth = constantWidth;
            return db.AddEnityToModelSpace(pLine);
        }
        /// <summary>
        /// 绘制矩形
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="point1">第一个点</param>
        /// <param name="point2">对角点</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddRectToModelSpace(this Database db, Point2d point1, Point2d point2)
        {
            //声明多段线
            Polyline pLine = new Polyline();
            //计算矩形的四个顶点坐标
            Point2d p1 = new Point2d(Math.Min(point1.X, point2.X), Math.Min(point1.Y, point2.Y));
            Point2d p2 = new Point2d(Math.Max(point1.X, point2.X), Math.Min(point1.Y, point2.Y));
            Point2d p3 = new Point2d(Math.Max(point1.X, point2.X), Math.Max(point1.Y, point2.Y));
            Point2d p4 = new Point2d(Math.Min(point1.X, point2.X), Math.Max(point1.Y, point2.Y));
            //添加多段线的顶点
            pLine.AddVertexAt(0, p1, 0, 0, 0);
            pLine.AddVertexAt(0, p2, 0, 0, 0);
            pLine.AddVertexAt(0, p3, 0, 0, 0);
            pLine.AddVertexAt(0, p4, 0, 0, 0);
            //闭合多段线
            pLine.Closed = true;
            return db.AddEnityToModelSpace(pLine);
        }

        /// <summary>
        /// 绘制内接正多边形
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="center">多边形所在圆的圆心</param>
        /// <param name="radius">所在圆的半径</param>
        /// <param name="sideNum">边数</param>
        /// <param name="startDegree">起始角度</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddPolygonToModelSpace(this Database db, Point2d center,double radius,int sideNum,double startDegree)
        {
            //声明多段线对象
            Polyline pLine = new Polyline();
            //判断边数是否符合要求
            if (sideNum < 3)
            {
                return ObjectId.Null;
            }
            Point2d[] point = new Point2d[sideNum];
            double angle = startDegree.DegreeToAngle();
            //计算每个顶点的坐标
            for (int i = 0; i < sideNum; i++)
            {
                point[i] = new Point2d(center.X + radius * Math.Cos(angle), center.Y + radius * Math.Sin(angle));
                pLine.AddVertexAt(i, point[i], 0, 0, 0);
                angle += Math.PI * 2 / sideNum;
            }
            //闭合多段线
            pLine.Closed = true;
            return db.AddEnityToModelSpace(pLine);
        }

        /// <summary>
        /// 绘制椭圆
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="center">椭圆中心</param>
        /// <param name="majorRadius">长轴长度</param>
        /// <param name="shortRadius">短轴长度</param>
        /// <param name="degere">长轴与X轴夹角,角度值</param>
        /// <param name="startDegree">起始角度</param>
        /// <param name="endDegree">终止角度</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddEllipseToModelSpace(this Database db, Point3d center, double majorRadius, double shortRadius, double degere,double startDegree,double endDegree)
        {
            //计算相关参数
            double ratio = shortRadius/majorRadius;
            Vector3d majorAxis = new Vector3d(majorRadius * Math.Cos(degere.DegreeToAngle()),majorRadius * Math.Sin(degere.DegreeToAngle()),0);
            //(new Point3d(100, 100, 0), Vector3d.ZAxis, new Vector3d(100, 0, 0), 0.4, 0, 2*Math.PI);
            //声明椭圆对象
            Ellipse elli = new Ellipse(center, Vector3d.ZAxis, majorAxis, ratio, startDegree.DegreeToAngle(), endDegree.DegreeToAngle());
            return db.AddEnityToModelSpace(elli);
        }
        /// <summary>
        /// 绘制椭圆
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="majorPoint1">长轴端点1</param>
        /// <param name="majorPoint2">长轴端点2</param>
        /// <param name="shortRadius">短轴的长度</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddEllipseToModelSpace(this Database db, Point3d majorPoint1, Point3d majorPoint2, double shortRadius)
        {
            //椭圆的圆心
            Point3d center = majorPoint1.GetCenterPointBetweenTwoPoint(majorPoint2);
            //短轴与长轴的比
            double ratio = 2*shortRadius / majorPoint1.GetDistanceBetweenTwoPoint(majorPoint2);
            //长轴的向量
            Vector3d majorAxis = majorPoint2.GetVectorTo(center);
            Ellipse elli = new Ellipse(center, Vector3d.ZAxis,majorAxis, ratio, 0, 2 * Math.PI);

            return db.AddEnityToModelSpace(elli);
        }
        /// <summary>
        /// 绘制椭圆
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="point1">所在矩形的顶点1</param>
        /// <param name="point2">所在矩形的顶点1</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddEllipseToModelSpace(this Database db, Point3d point1, Point3d point2)
        {
            //椭圆的圆心
            Point3d center = point1.GetCenterPointBetweenTwoPoint(point2);
            double ratio = Math.Abs((point1.Y - point2.Y)/(point1.X - point2.X) );
            Vector3d majorVector = new Vector3d(Math.Abs((point1.X - point2.X)) / 2, 0, 0);
            //声明椭圆对象
            Ellipse elli = new Ellipse(center, Vector3d.ZAxis, majorVector, ratio, 0, 2 * Math.PI);
            return db.AddEnityToModelSpace(elli);
        }
    }
}
